<?php

namespace app\admin\service;

use app\admin\model\Menu;
use Tinywan\ExceptionHandler\Exception\BadRequestHttpException;
use common\enum\ResultCode;
use Tinywan\ExceptionHandler\Exception\NotFoundHttpException;
use Webman\Event\Event;

class MenuService extends BaseCurdService
{
    /**
     * 获取菜单列表
     * @param array $params 查询参数
     * @return array
     */
    public function getList(array $params): array
    {
        $query = Menu::query();
        // 菜单列表按sort升序、id升序排序
        return $this->paginateQuery($query, $params, ['name'], ['status'], ['sort' => 'asc', 'id' => 'asc']);
    }

    /**
     * 获取菜单详情
     * @param int $id 菜单ID
     * @return Menu|null
     */
    public function getInfo(int $id): ?Menu
    {
        $menu = Menu::find($id);
        if (!$menu) {
            throw new NotFoundHttpException(ResultCode::DATA_NOT_FOUND->getDescription());
        }
        return $menu;
    }

    /**
     * 创建菜单
     * @param array $data 菜单数据
     * @return Menu
     */
    public function create(array $data): Menu
    {
        // 检查菜单名称是否已存在
        if (Menu::where('name', $data['name'])->where('parent_id', $data['parent_id'])->exists()) {
            throw new BadRequestHttpException('菜单名称已存在');
        }
        return Menu::create($data);
    }

    /**
     * 更新菜单
     * @param int $id 菜单ID
     * @param array $data 更新数据
     * @return bool
     */
    public function update(int $id, array $data): bool
    {
        $menu = Menu::find($id);
        if (!$menu) {
            throw new NotFoundHttpException(ResultCode::DATA_NOT_FOUND->getDescription());
        }
        // 检查菜单名称是否已存在
        if (isset($data['name']) && Menu::where('name', $data['name'])->where('parent_id', $data['parent_id'] ?? $menu->parent_id)->where('id', '!=', $id)->exists()) {
            throw new BadRequestHttpException('菜单名称已存在');
        }
        $result = $menu->update($data);
        if ($result) {
            Event::emit('menu.updated', ['menuId' => $id]);
        }
        return $result;
    }

    /**
     * 删除菜单
     * @param int $id 菜单ID
     * @return bool|null
     */
    public function delete(int $id): ?bool
    {
        $menu = Menu::find($id);
        if (!$menu) {
            throw new NotFoundHttpException(ResultCode::DATA_NOT_FOUND->getDescription());
        }
        // 检查是否有子菜单
        if (Menu::where('parent_id', $id)->exists()) {
            throw new BadRequestHttpException('请先删除子菜单');
        }
        $result = $menu->delete();
        if ($result) {
            Event::emit('menu.deleted', ['menuId' => $id]);
        }
        return $result;
    }
}